<template>
  <div class="table">
    <div class="dataTable">
      <el-table
          id="zTable"
          ref="multipleTable"
          v-loading="options.loading"
          :data="list"
          :stripe="options.stripe"
          :border="options.border"
          :default-sort="options.defaultSort||{prop: 'id',order: 'descending'}"
          :row-style="options.rowStyle"
          :row-class-name="options.rowClassName"
          @row-click="rowClick"
          @sort-change='sortChange'
          @selection-change="handleSelectionChange">
        <!--region 选择框-->
        <el-table-column v-if="options.multipleSelect" type="selection" style="width: 55px;">
        </el-table-column>
        <!--endregion-->
        <!--region 数据列-->
        <template v-for="(column, index) in columns">
          <el-table-column :prop="column.prop"
                           :label="column.label"
                           :align="column.align"
                           :sortable="column.sortable"
                           :show-overflow-tooltip="column.showOverflowTooltip"
                           :width="column.width"
                           :key="index">
            <template slot-scope="scope">
              <template v-if="!column.render">
                <template v-if="column.formatter">
                  <span v-html="column.formatter(scope.row, column)"/>
                </template>
                <template v-else>
                  <span>{{ scope.row[column.prop] }}</span>
                </template>
              </template>
              <template v-else>
                <expand-dom :column="column" :row="scope.row" :render="column.render"
                            :index="index"/>
              </template>
            </template>
          </el-table-column>
        </template>
        <!--endregion-->
        <!--region 按钮操作组-->
        <el-table-column :label="operates.title===undefined?'操作':operates.title" align="center"
                         :width="(operates.width===undefined || operates.width==='auto') && operates.list?operates.list.length*100:operates.width"
                         :fixed="(device==='desktop')&&(operates.fixed===undefined?'right':operates.fixed)"
                         v-if="(operates && operates.list && operates.list.length > 0)"
        >
          <template slot-scope="scope">
            <div>
              <template v-for="(btn, key) in operates.list">
                <el-button :type="btn.type" size="mini" :icon="btn.icon"
                           v-permission="btn.permission"
                           :disabled="btn.disabled(scope.$index,scope.row)"
                           :plain="btn.plain" @click.native.prevent="btn.method(key,scope.row)"
                           :key="key">{{
                    btn.label
                  }}
                </el-button>
              </template>
            </div>
          </template>
        </el-table-column>
        <!--endregion-->
      </el-table>
    </div>
    <!--region 分页-->
    <el-pagination class="pageRow" :style="{'text-align': device==='mobile'?'center':'right'}" v-if="pagination"
                   @size-change="handleSizeChange"
                   @current-change="handleIndexChange"
                   :page-size="pagination.pageSize"
                   :small="device==='mobile'"
                   :page-sizes="pagination.pageArray" :current-page="pagination.pageNum"
                   :layout="device==='mobile'?'prev, pager, next, jumper':'total,sizes, prev, pager, next, jumper'"
                   :hide-on-single-page="pagination.total<=10"
                   :total="pagination.total"/>
  </div>
</template>
<script lang="ts">
import {Component, Emit, Prop, Vue} from 'vue-property-decorator';
import {Getter} from 'vuex-class';
import {filterParams} from '@/utils';

@Component({
  components: {
    expandDom: {
      functional: true,
      props: {
        row: Object,
        render: Function,
        index: Number,
        column: {
          type: Object,
          default: null
        }
      },
      render: (createElement: any, context: any) => {
        //详细使用方法见 https://cn.vuejs.org/v2/guide/render-function.html#createElement-%E5%8F%82%E6%95%B0
        const params = {
          row: context.props.row,
          index: context.props.index,
          column: ''
        };
        if (context.props.column) {
          params.column = context.props.column;
        }
        return context.props.render(createElement, params);
      }
    }
  }
})
export default class DataTable extends Vue {
  @Prop() private api!: any;
  @Prop() private columns!: Array<any>;// 需要展示的列 === prop：列数据对应的属性，label：列名，align：对齐方式，width：列宽,showOverflowTooltip:隐藏多余字符
  @Prop() private operates!: any;// width:按钮列宽，fixed：是否固定（left,right）,按钮集合 === label: 文本，type :类型（primary / success / warning / danger / info / text），show：是否显示，icon：按钮图标，plain：是否朴素按钮，disabled：是否禁用，method：回调方法
  @Prop({
    default: () => ({//分页参数
      pageNum: 1,
      pageSize: 10,
      pageArray: [10, 30, 50, 100],
      total: 0
    })
  })
  private pagination!: any;
  @Prop({
    default: () => ({//表格样式参数
      stripe: false, // 是否为斑马纹 table
      loading: false, // 是否添加表格loading加载动画
      highlightCurrentRow: false, // 是否支持当前行高亮显示
      multipleSelect: false, // 是否支持列表项选中功能
      defaultSort: {
        prop: 'id',
        order: 'descending'
      },
      border: false
    })
  }) private options!: any;

  @Prop() private query: any;//查询参数
  @Getter('device') private device!: string;
  private list: Array<any> = [];
  private multipleSelection: Array<any> = [];// 多行选中

  /* created() {
       this.change();
   }*/

  // 切换每页显示的数量
  handleSizeChange(size: number) {
    if (this.pagination) {
      this.pagination.pageNum = 1;
      this.pagination.pageSize = size;
      this.change();
    }
  }

  // 切换页码
  handleIndexChange(pageNum: number) {
    if (this.pagination) {
      this.pagination.pageNum = pageNum;
      this.change();
    }
  }

  sortChange(column: any, prop: any, order: any) {
    if (column) {
      this.pagination.orderByColumn = column.prop;
      if (column.order === 'descending') {
        this.pagination.isAsc = 'desc';
      } else if (column.order === 'ascending') {
        this.pagination.isAsc = 'asc';
      } else {
        delete this.pagination['isAsc'];
      }
    } else {
      delete this.pagination['orderByColumn'];
      delete this.pagination['isAsc'];
    }
    this.change();
  }

  @Emit('update:pagination')
  change() {
    this.refresh();
    return this.pagination;
  }

  // 多行选中
  @Emit('handleSelectionChange')
  @Emit('handle-selection-change')
  handleSelectionChange(val: any) {
    this.multipleSelection = val;
    return val;
  }

  @Emit('rowClick')
  @Emit('row-click')
  rowClick(val: any) {
    return val;
  }

  toggleSelection(row: any) {
    if (row) {
      (this.$refs.multipleTable as any).toggleRowSelection(row);
    } else {
      (this.$refs.multipleTable as any).clearSelection();
    }
  }

  handleParams() {
    const options = this.query || {};
    if (this.pagination) {
      options.pageNum = this.pagination.pageNum;
      options.pageSize = this.pagination.pageSize;
      options.orderByColumn = this.pagination.orderByColumn;
      options.isAsc = this.pagination.isAsc;
    }
    if (!options.orderByColumn) {
      options.orderByColumn = this.options.defaultSort ? this.options.defaultSort.prop || 'id' : 'id';
    }
    if (!options.isAsc) {
      if (this.options.defaultSort && this.options.defaultSort.order) {
        if (this.options.defaultSort.order === 'descending') {
          options.isAsc = 'desc';
        } else if (this.options.defaultSort.order === 'ascending') {
          options.isAsc = 'asc';
        } else {
          delete options.isAsc['isAsc'];
        }
      } else {
        options.isAsc = 'desc';
      }
    }
    return filterParams(options);
  }

  refreshData(api: any) {
    api(this.handleParams()).then((res: any) => {
      if (res.rows && res.rows.length === 0 && res.total !== 0) {//如果当前页数据为空，并且总条数大于0，那么改变页码，刷新数据
        this.pagination.pageNum = this.pagination.pageNum - 1;
        this.refresh();
      }
      this.list = res.rows;
      this.pagination.total = res.total;
      this.handleEvent(res.rows);
    }).catch((e) => {
      console.log(e);
    });
  }

  @Emit('handleEvent')
  @Emit('handle-event')
  handleEvent(val) {
    return val;
  }

  refresh() {
    this.refreshData(this.api);
  }

  activated() {
    this.refreshData(this.api);
  }
}
</script>

<style scoped lang="scss">
.table {
  width: calc(100%);

  .dataTable {
    flex: 1;
  }


  .pageRow {
    margin: 10px;
    overflow: hidden;
  }
}
</style>

